home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / sectools / fragrouter / Libnet-0.99b / src / write_ip.c < prev   
Encoding:
C/C++ Source or Header  |  1999-07-26  |  9.2 KB  |  320 lines

  1. /*
  2.  *  $Id: write_ip.c,v 1.3 1999/06/24 18:35:34 dugsong Exp $
  3.  *
  4.  *  libnet
  5.  *  write_ip.c - writes a prebuilt IP packet to the network
  6.  *
  7.  *  Copyright (c) 1998, 1999 Mike D. Schiffman <mike@infonexus.com>
  8.  *                           route|daemon9 <route@infonexus.com>
  9.  *  All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions and the following disclaimer.
  16.  * 2. Redistributions in binary form must reproduce the above copyright
  17.  *    notice, this list of conditions and the following disclaimer in the
  18.  *    documentation and/or other materials provided with the distribution.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30.  * SUCH DAMAGE.
  31.  *
  32.  */
  33.  
  34. #if (HAVE_CONFIG_H)
  35. #include "../include/config.h"
  36. #endif
  37. #include "../include/libnet.h"
  38.  
  39. int
  40. write_ip(int sock, u_char *buf, int len)
  41. {
  42.     int c;
  43.     struct sockaddr_in sin;
  44.     struct ip *ip_hdr;
  45.  
  46. #if (RAW_IS_COOKED)
  47.     return write_ip_via_datalink(buf,len);
  48. #endif /* RAW_IS_COOKED */
  49.  
  50.     ip_hdr = (struct ip *)buf;
  51.     
  52. #if (BSD_BYTE_SWAP)
  53.     /*
  54.      *  For link access, we don't need to worry about the inconsistencies of
  55.      *  certain BSD kernels.  However, raw socket nuances abound.  Certain
  56.      *  BSD implmentations require the ip_len and ip_off fields to be in host
  57.      *  byte order.  It's MUCH easier to change it here than inside the bpf
  58.      *  writing routine.
  59.      */
  60.     ip_hdr->ip_len = FIX(ip_hdr->ip_len);
  61.     ip_hdr->ip_off = FIX(ip_hdr->ip_off);
  62. #endif
  63.  
  64.     memset(&sin, 0, sizeof(struct sockaddr_in));
  65.     sin.sin_family      = AF_INET;
  66.     sin.sin_addr.s_addr = ip_hdr->ip_dst.s_addr;
  67.  
  68.     c = sendto(sock, buf, len, 0, (struct sockaddr *)&sin,
  69.            sizeof(struct sockaddr));
  70.     if (c != len)
  71.     {
  72. #if (__DEBUG)
  73.         fprintf(stderr, "write_ip: %d bytes written (%s)\n", c, strerror(errno));
  74. #endif
  75.     }
  76. #if (BSD_BYTE_SWAP)
  77.     ip_hdr->ip_len = UNFIX(ip_hdr->ip_len);
  78.     ip_hdr->ip_off = UNFIX(ip_hdr->ip_off);
  79. #endif
  80.     
  81.     return (c);
  82. }
  83.  
  84. #if (RAW_IS_COOKED)
  85. /*
  86.  * write_ip_via_datalink
  87.  *
  88.  * The intent of this function is to provide an easy mechanism for someone
  89.  * to send an IP packet that is inserted into the network via the datalink
  90.  * access interfaces. This is useful in situations where raw sockets are 
  91.  * cooked, which can prevent programs using write_ip from working on certain 
  92.  * Unixes.
  93.  * To pull this off, we have to determine a source and destination MAC
  94.  * address for the packet, as well as the correct interface to send it on.
  95.  * 
  96.  * This has currently only been implemented and tested on solaris 2.6/2.5.1.
  97.  */
  98.  
  99. int
  100. write_ip_via_datalink(u_char *buf, int len)
  101. {
  102.     char ebuf[1024];
  103.     const u_char *broadcast_hwaddr="\xff\xff\xff\xff\xff\xff";
  104.  
  105.     static u_long cached_dest_ip=0;
  106.     static u_char *cached_device=NULL;
  107.     static struct link_int *cached_linkent=NULL;
  108.  
  109.     struct link_int *linkent=NULL;
  110.     u_long local_ip;
  111.     u_long dest_ip;
  112.  
  113.     u_char *sbuf;
  114.     static u_char source_hwaddr[6];
  115.     static u_char dest_hwaddr[6];
  116.     u_long gateway_ip;
  117.     u_char *device;
  118.  
  119.     struct ip *ip_hdr;
  120.     int c;
  121.  
  122.     ip_hdr = (struct ip *)(buf);
  123.     dest_ip = ip_hdr->ip_dst.s_addr;
  124.     
  125. #if (__DEBUG)
  126.     fprintf(stderr, "entering write_ip_via_datalink\n");
  127. #endif
  128.  
  129.     if (cached_dest_ip == dest_ip)
  130.     {
  131. #if (__DEBUG)
  132.         fprintf(stderr, "taking cached shortcut\n");
  133. #endif
  134.         linkent=cached_linkent;
  135.         device=cached_device;
  136.         goto send_it;
  137.     }
  138.  
  139.     /*  
  140.      * Step one: Pick the local interface to send the packet on. 
  141.      *
  142.      * This requires support for the udp socket trick. If it isn't there
  143.      * then we will just pick the first available interface and try it out.
  144.      */
  145.  
  146.     local_ip=libnet_get_interface_by_dest(dest_ip,ebuf);
  147.  
  148.     if (local_ip==-1)
  149.     {
  150.         fprintf(stderr,"libnet_get_interface_by_dest: %s\n",ebuf);
  151.         return -1;
  152.     }
  153.     if (local_ip==0) /* We must be in Solaris 2.5.1 or lower. */
  154.     {
  155.         /*struct sockaddr_in tempsin;*/
  156.  
  157. #if (__DEBUG)
  158.         fprintf(stderr, "libnet_get_interface_by_dest is not supported\n");
  159. #endif
  160.         /* XXX - This function is currently broken under Solaris 2.5.1
  161.         if (libnet_select_device(&tempsin,&device,ebuf)==-1)
  162.         {
  163.             fprintf(stderr,"libnet_select_device: %s\n",ebuf);
  164.             return -1;
  165.         }
  166.         local_ip=tempsin.sin_addr.s_addr;*/
  167.          
  168.         /* Instead, we will try a couple of devices and see what happens. */
  169.  
  170.         if ((linkent=libnet_open_link_interface("le0",ebuf))==NULL)
  171.         {
  172.             if ((linkent=libnet_open_link_interface("hme0",ebuf))==NULL)
  173.             {
  174.                 fprintf(stderr,"I can't find the interface to use.\n");
  175.                 return -1;
  176.             }
  177.             else
  178.         device="hme0";
  179.         }
  180.         else
  181.             device="le0";
  182.      
  183.         if ((local_ip=get_ipaddr(linkent,device,ebuf))==-1)
  184.         {
  185.             fprintf(stderr,"get_ipaddr: %s\n",ebuf);
  186.             return -1;
  187.         }
  188.     }
  189.     else
  190.     {
  191.         if (libnet_select_device_by_ip(&device,local_ip,ebuf)==-1)
  192.         {
  193.             fprintf(stderr,"libnet_select_device_by_ip: %s\n",ebuf);
  194.             return -1;
  195.         }
  196.     }
  197.  
  198. #if (__DEBUG)
  199.     fprintf(stderr, "Using device %s with local IP of %s\n",device,
  200.             host_lookup(local_ip,0));
  201. #endif 
  202.  
  203.     /*
  204.      * Step two: Get the source MAC address.
  205.      */
  206.  
  207.     if (libnet_query_arp(local_ip,source_hwaddr,ebuf)==-1)
  208.     {
  209.         fprintf(stderr,"libnet_query_arp_cache: %s\n",ebuf);
  210.         return -1;
  211.     }
  212.  
  213. #if (__DEBUG)
  214.     fprintf(stderr, "Using source MAC address %x:%x:%x:%x:%x:%x\n",
  215.             source_hwaddr[0], source_hwaddr[1], source_hwaddr[2],
  216.             source_hwaddr[3], source_hwaddr[4], source_hwaddr[5]);
  217. #endif 
  218.  
  219.     /*
  220.      * Step three: Get the destination MAC address.
  221.      *
  222.      * To really do this right, we use a routing socket to query the kernel
  223.      * for the appropriate gateway. If it is our own interface then we need
  224.      * to do an ARP resolution of the target IP. Otherwise, we need to do
  225.      * an ARP resolution of the gateway IP. If there is no support for routing
  226.      * sockets then we can use the broadcast MAC address which seems to work
  227.      * fine.
  228.      */
  229.  
  230.     if ((gateway_ip=libnet_get_next_hop(dest_ip, ebuf))==-1)
  231.     {
  232. #if (__DEBUG)
  233.         fprintf(stderr, "libnet_get_next_hop failed: %s\n",ebuf);
  234. #endif 
  235.         memcpy(dest_hwaddr,broadcast_hwaddr,6);
  236.     }
  237.     else
  238.     {
  239.         if (gateway_ip==local_ip)
  240.         {
  241.             /* This is on our subnet. We need to request the ARP address of
  242.              * the destination IP. */
  243.             if (libnet_active_query_arp(dest_ip,dest_hwaddr,device,ebuf)==-1)
  244.             {
  245. #if (__DEBUG)
  246.                 fprintf(stderr, "libnet_query_arp failed: %s\n",ebuf);
  247. #endif 
  248.                 memcpy(dest_hwaddr,broadcast_hwaddr,6);
  249.             }
  250.         }
  251.         else /* We need to send to a gateway. */
  252.         {
  253.             if (libnet_active_query_arp(gateway_ip,dest_hwaddr,device,ebuf)==-1)
  254.             {
  255. #if (__DEBUG)
  256.                 fprintf(stderr, "libnet_query_arp failed: %s\n",ebuf);
  257. #endif 
  258.                 memcpy(dest_hwaddr,broadcast_hwaddr,6);
  259.             }
  260.         }
  261.     }
  262.  
  263. #if (__DEBUG)
  264.     fprintf(stderr, "Using destination MAC address %x:%x:%x:%x:%x:%x\n",
  265.             dest_hwaddr[0], dest_hwaddr[1], dest_hwaddr[2],
  266.             dest_hwaddr[3], dest_hwaddr[4], dest_hwaddr[5]);
  267. #endif 
  268.  
  269.     /*
  270.      * Step four: ship it.
  271.      */
  272.  
  273.     if (!linkent && (linkent=libnet_open_link_interface(device,ebuf))==NULL)
  274.     {
  275.         fprintf(stderr,"libnet_open_link_interface: %s\n",ebuf);
  276.         return -1;
  277.     }
  278.  
  279. send_it:
  280.  
  281.     if (libnet_init_packet(ETH_H + len, &sbuf)==-1)
  282.     {
  283.         fprintf(stderr,"libnet_init_packet: %s\n",ebuf);
  284.         return -1;
  285.     }
  286.  
  287.     libnet_build_ethernet(dest_hwaddr,source_hwaddr,ETHERTYPE_IP,NULL,0,sbuf);
  288.  
  289.     memcpy(sbuf+ETH_H,buf,len);
  290.     libnet_do_checksum(sbuf+ETH_H, IPPROTO_IP, ip_hdr->ip_hl*4);
  291.     if ((c=libnet_write_link_layer(linkent,device,sbuf,ETH_H+len))<0)
  292.     {
  293.         fprintf(stderr,"libnet_write_link_later: %s\n",strerror(errno));
  294.         return -1;
  295.     }
  296.  
  297.     cached_dest_ip=dest_ip;
  298.     cached_device=device;
  299.     if (cached_linkent && (cached_linkent != linkent))
  300.     {
  301.         libnet_close_link_interface(cached_linkent);
  302.     }
  303.     cached_linkent=linkent;
  304.  
  305.     libnet_destroy_packet(&sbuf);
  306.  
  307.     if (c != len +ETH_H)
  308.     {
  309. #if (__DEBUG)
  310.         fprintf(stderr, "write_ip_via_datalink: %d bytes written (%s)\n", c, strerror(errno));
  311. #endif
  312.     }
  313.  
  314.     return (c-ETH_H);
  315.  
  316. }
  317. #endif /* RAW_IS_COOKED */
  318.  
  319. /* EOF */
  320.